package org.bdware.irp.irplib.core;

import org.bdware.irp.irplib.exception.IrpMessageEncodeException;
import org.bdware.irp.irplib.util.IrpCommon;
import org.bdware.irp.irplib.util.EncoderUtils;
/**
 *
 * Description:
 * <p>
 *  Message Envelope implementation
 * </p>
 * Time:2021-07<br>
 *
 * @author：pku<br>
 * @version:$Revision: 1.0 $<br>
 * @since 1.0
 */
public class IrpMessageEnvelope {
    public byte majorVersion;
    public byte minVersion;
    private short messageFlag;
    public int sessionId;
    public int requestId;
    public int sequenceNumber;
    public int messageLength;

    //bit flag in messageFlag
    private boolean isComPressed;
    private boolean isEnCrypted;
    private boolean isTruncated;

    /**
     * IrpMessageEnvelope Constructor
     */
    public IrpMessageEnvelope(){
        this.majorVersion = IrpCommon.DEFAULT_MAJOR_VERSION;
        this.minVersion = IrpCommon.DEFAULT_MINOR_VERSION;
        this.sessionId = 0;
        this.requestId = 0;
        this.sequenceNumber = 0;
        this.messageLength = 0;
        this.setFlagsByMessageFlag((short)0);
    }

    public IrpMessageEnvelope(int requestId){
        this.majorVersion = IrpCommon.DEFAULT_MAJOR_VERSION;
        this.minVersion = IrpCommon.DEFAULT_MINOR_VERSION;
        this.sessionId = 0;
        this.requestId = requestId;
        this.sequenceNumber = 0;
        this.messageLength = 0;
        this.setFlagsByMessageFlag((short)0);
    }

    public IrpMessageEnvelope(byte majorVersion, byte minVersion, short messageFlag, int sessionId, int requestId,int sequenceNumber, int messageLength){
        this.majorVersion = majorVersion;
        this.minVersion = minVersion;
        this.sessionId = sessionId;
        this.requestId = requestId;
        this.sequenceNumber = sequenceNumber;
        this.messageLength = messageLength;
        this.setFlagsByMessageFlag(messageFlag);
    }

    /**
     * Operations for messageFlag
     */
    public void setFlagsByMessageFlag(short messageFlag){
        this.messageFlag = messageFlag;
        this.isComPressed = (messageFlag < 0);
        this.isEnCrypted = ((short)(messageFlag << 1 ) < 0);
        this.isTruncated = ((short)(messageFlag << 2 ) < 0);
    }

    public short getMessageFlagByFlags(){
        this.messageFlag = 0;
        if(this.isComPressed) this.messageFlag = (short)(this.messageFlag | 0x8000);
        if(this.isEnCrypted) this.messageFlag = (short)(this.messageFlag | 0x4000);
        if(this.isTruncated) this.messageFlag = (short)(this.messageFlag | 0x2000);
        return this.messageFlag;
    }

    public boolean getComPressed(){
        return this.isComPressed;
    }

    public boolean getEnCrypted(){
        return this.isEnCrypted;
    }

    public boolean getTruncated(){
        return this.isTruncated;
    }

    public void setComPressed(boolean isComPressed){
        this.isComPressed = isComPressed;
    }

    public void setEnCrypted(boolean isEnCrypted){
        this.isEnCrypted = isEnCrypted;
    }

    public void setTruncated(boolean isTruncated){
        this.isTruncated = isTruncated;
    }

    //return the encodedCredential(if not exists, encode the message credential first)
    public final byte[] getEncodeEnvelope() throws IrpMessageEncodeException {
        //encode the credential
        byte[] encodedEnvelope = EncoderUtils.encodeMessageEnvelope(this);
        return encodedEnvelope;
    }
}
